﻿using CarparkEnum;
using CarparkIMS_Model;
using Common;
using LogUtility;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace CarparkBusiness
{
    public class MainCalcControlLer
    {
        private ParkingSetting ParkingSetting { get; set; }
        private readonly IMSContext Context;
        private readonly ILogger<MainCalcControlLer> Logger;
        private List<llqqCameraDoorMapping> llqqCameraDoorMappings { get; set; }
        public MainCalcControlLer(IMSContext context, ILogger<MainCalcControlLer> logger, IOptions<ParkingSetting> parkingSetting)
        {
            Context = context;

            if (ParkingSetting.Get() == null)
            {
                ParkingSetting = parkingSetting.Value ?? new ParkingSetting();
            }
            else
            {
                ParkingSetting = ParkingSetting.Get();
            }
            Logger = logger ?? throw new ArgumentNullException(nameof(logger));
            string loggerline = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff}] [UNIT CALC INITIALIZEING......]";
            Logger.LogInformation(loggerline);
            CommonBase.OperateDateLoger(loggerline);
            llqqCameraDoorMappings = Context.llqqCameraDoorMapping.Where(c => c.Deleted == false && c.ParkingNoCalcType == (int)ParkingNoCalcType.PLACE_DURATION).ToList();
        }
        public async Task Run(string[] args)
        {
            Logger.LogInformation("Starting...");

            Console.WriteLine("Hello-----------------------------------------------------------------------------!");
#if DEBUG
            Console.WriteLine("Hello Test!");
            Console.WriteLine("Hello Test!");
            Console.WriteLine("Hello Test!");
            Console.WriteLine("Hello Test!");
#endif
            foreach (var item in llqqCameraDoorMappings)
            {
                Logger.LogInformation($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff K}] [FUNC:llqqCameraDoorMapping List] [CameraIP={item.CameraIP}] [PlaceNo={item.ParkingPlaceSharpNumber}/ParkingPlaceId={item.ParkingPlaceId}/ParkingNoCalcType={item.ParkingNoCalcType}/DoorID={item.DoorID}]]");
                await Task.Delay(0);
            }

            foreach (var item in llqqCameraDoorMappings)
            {
                if (CheckParkingPlaceLog(item.ParkingPlaceId))
                {
                    Logger.LogInformation($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff K}] [CLS::ParkingPlaceUnitCalc]");

                    ParkingNoCalcType parkingNoCalcType = (ParkingNoCalcType)item.ParkingNoCalcType;
                    using ParkingPlaceUnitCalc placeUnitCalc = new ParkingPlaceUnitCalc(Context, parkingNoCalcType, item.ParkingPlaceId, ParkingSetting.IntervalSeconds, ParkingSetting.AllowanceSeconds, ParkingSetting.MaxIntervalTimes, ParkingSetting.IntervalTimes);

                    Logger.LogInformation($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff K}] [CLS::placeUnitCalc][IsCompleted={placeUnitCalc.IsCompleted}][placeUnitCalc.Invalid={placeUnitCalc.Invalid}][IntervalSeconds={ParkingSetting.IntervalSeconds}]");

                    string jsonOfPlaceUnitCalc = JsonConvert.SerializeObject(placeUnitCalc);
                    Logger.LogInformation($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff K}] [CLASS::MainCalc.foreach][{jsonOfPlaceUnitCalc}]");

                    if (placeUnitCalc.Invalid == false && placeUnitCalc.IsUpdate == false)
                    {
                        await placeUnitCalc.InsetNumberPlate(placeUnitCalc);
                    }
                    else if (placeUnitCalc.Invalid == false && placeUnitCalc.IsUpdate == true)
                    {
                        await placeUnitCalc.UpdateNumberPlate(placeUnitCalc);
                    }
                    //clear  
                    placeUnitCalc.Dispose();
                    Logger.LogInformation($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff K}] [FUNC::placeUnitCalc.Dispose]");
                }
                else
                {
                    Logger.LogInformation($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff K}] [CLS::MainCalcControlLer.foreach][NO LOG : {item.ParkingPlaceId}/{item.ParkingPlaceSharpNumber}]");
                }
                await Task.Delay(0);
            }
            Logger.LogInformation("Finished!");

            await FileFlush(args);

            await Task.CompletedTask;
        }
        private bool CheckParkingPlaceLog(string parkingPlaceId)
        {
            DateTime HistDateBegin = DateTime.Now.AddMonths(-1);
            bool isExistLog = Context.llqqPlateLog.Where(c => c.ParkingPlaceId.Contains(parkingPlaceId) && c.OccuredDatetime > HistDateBegin).Any();
            return isExistLog;
        }

        public async Task FileFlush(string[] args)
        {
            string curFolderPath = Environment.CurrentDirectory;  //  = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            //Console.WriteLine("Hello!!! \n{0} {1}", curFolderPath, args.ToString());

            await Task.Delay(1000);

#if DEBUG
            Console.WriteLine("FILE FLUSH!");
#endif
            DateTime occurDatetime = DateTime.Now.AddDays(-ParkingSetting.HistoryRecordRemain);
            var numplatelist = Context.llqqNumberPlate.Where(c => c.StartDatetime <= occurDatetime).ToList();
            if (numplatelist.Any())
            {
                string logplateCalc = $"NUMBERPLATE HISTORY LIST DELETED! RECORD ={numplatelist.Count()}";
                Console.WriteLine(logplateCalc);
                Context.llqqNumberPlate.RemoveRange(numplatelist);
                CommonBase.OperateDateLoger(logplateCalc);
            }

            var plateLogs = Context.llqqPlateLog.Where(c => c.OccuredDatetime <= occurDatetime).ToList();
            if (plateLogs.Any())
            {
                string loggerplate = $"NUMBER PLATE HISTORY LOG DELETED! RECORD ={plateLogs.Count()}";
                Console.WriteLine(loggerplate);
                Context.llqqPlateLog.RemoveRange(plateLogs);
                await Context.SaveChangesAsync();
                CommonBase.OperateDateLoger(loggerplate);

                //file remove
                string imgPath = Path.Combine(curFolderPath, "img");

                foreach (var item in plateLogs)
                {
                    string filename = $"{item.ID}.jpg";
                    string pathFilename = Path.Combine(imgPath, filename);

                    if (File.Exists(pathFilename))
                    {
                        try
                        {
                            FileInfo fileInfo = new FileInfo(pathFilename);
                            fileInfo.Delete();
                            string logfilename = $"[FUNC::FileFlush][FILE DELETE {filename}";
                            Logger.LogWarning(logfilename);
                        }
                        catch (Exception ex)
                        {
                            string logfilename = $"[FUNC::FileFlush][FILE DELETE] [EXCEPTION][{ex.Message}]";
                            Logger.LogWarning(logfilename);
                            CommonBase.OperateDateLoger(loggerplate);
                        }
                    }
                }
            }

            //if (Directory.Exists(imgPath))
            //{
            //    DirectoryInfo imgInfo = new DirectoryInfo(imgPath);
            //    var fileLists = imgInfo.GetFiles();
            //    foreach (var item in fileLists)
            //    {
            //        if (item.CreationTime < occurDatetime)
            //        {
            //            item.Delete();
            //            string loggerDeleteImg = $"HISTORY IMAGE DELETED! RECORD ={item.FullName}";
            //            Console.WriteLine(loggerDeleteImg);
            //            CommonBase.OperateDateLoger(loggerDeleteImg);
            //        }
            //    }
            //}
        }
    }

    public class FileFlush
    {
        private ParkingSetting ParkingSetting { get; set; }
        private readonly IMSContext Context;
        private readonly ILogger<FileFlush> Logger;
        public FileFlush(IMSContext context, ILogger<FileFlush> logger, IOptions<ParkingSetting> parkingSetting)
        {
            Context = context;

            if (ParkingSetting.Get() == null)
            {
                ParkingSetting = parkingSetting.Value ?? new ParkingSetting();
            }
            else
            {
                ParkingSetting = ParkingSetting.Get();
            }
            Logger = logger ?? throw new ArgumentNullException(nameof(logger));
            string loggerline = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss fff}] [CLASS::FILE FLUSH RUNNING......]";
            Logger.LogInformation(loggerline);
            CommonBase.OperateDateLoger(loggerline);
        }
        public async Task Run(string[] args)
        {
            await Task.Delay(0);
            Logger.LogInformation("Starting...");

            string curFolderPath = Environment.CurrentDirectory;  //  = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            Console.WriteLine("Hello-----------------------------------------------------------------------------! \n{0}", curFolderPath);

#if DEBUG
            Console.WriteLine("FILE FLUSH!");
            Console.WriteLine("FILE FLUSH!");
            Console.WriteLine("FILE FLUSH!");
            Console.WriteLine("FILE FLUSH!");
#endif

            DateTime occurDatetime = DateTime.Now.AddDays(-ParkingSetting.HistoryRecordRemain);
            var numplatelist = Context.llqqNumberPlate.Where(c => c.StartDatetime <= occurDatetime).ToList();
            if (numplatelist.Any())
            {
                string logplateCalc = $"NUMBERPLATE HISTORY LIST DELETED! RECORD ={numplatelist.Count()}";
                Console.WriteLine(logplateCalc);
                Context.llqqNumberPlate.RemoveRange(numplatelist);
                CommonBase.OperateDateLoger(logplateCalc);
            }

            var plateLogs = Context.llqqPlateLog.Where(c => c.OccuredDatetime <= occurDatetime).ToList();
            if (plateLogs.Any())
            {
                string loggerplate = $"NUMBER PLATE HISTORY LOG DELETED! RECORD ={plateLogs.Count()}";
                Console.WriteLine(loggerplate);
                Context.llqqPlateLog.RemoveRange(plateLogs);
                CommonBase.OperateDateLoger(loggerplate);
            }

            string imgPath = Path.Combine(curFolderPath, "img");

            if (Directory.Exists(imgPath))
            {
                DirectoryInfo imgInfo = new DirectoryInfo(imgPath);
                var fileLists = imgInfo.GetFiles();
                foreach (var item in fileLists)
                {
                    if (item.CreationTime < occurDatetime)
                    {
                        item.Delete();
                        string loggerDeleteImg = $"HISTORY IMAGE DELETED! RECORD ={item.FullName}";
                        Console.WriteLine(loggerDeleteImg);
                        CommonBase.OperateDateLoger(loggerDeleteImg);
                    }
                }
            }
        }
    }

}
